package ru.hei.pointsserver.repository

import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.AfterEach
import org.junit.jupiter.api.Test
import org.springframework.beans.factory.annotation.Autowired
import org.testcontainers.shaded.org.apache.commons.lang3.RandomStringUtils
import reactor.test.StepVerifier.create
import ru.hei.pointsserver.entities.House

class HouseRepositoryTest @Autowired constructor(private val subject: HousesRepository) : BaseRepositoryTest() {

  @AfterEach
  fun clear() {
    create(subject.deleteAll())
      .expectComplete()
      .verify()
  }

  @Test
  fun `Should successfully save house`() {
    // Given
    val house = House(name = RandomStringUtils.randomAlphabetic(10), points = 10)

    // When
    create(subject.save(house))
      .expectSubscription()
      .assertNext {
        assertThat(it.id).isNotNull()
        assertThat(it.name).isEqualTo(house.name)
        assertThat(it.points).isEqualTo(10)
        assertThat(it.version).isNotNull()
      }
      .expectComplete()
      .verify()

    // Then
    create(subject.findAll())
      .expectSubscription()
      .assertNext {
        assertThat(it.id).isNotNull()
        assertThat(it.name).isEqualTo(house.name)
        assertThat(it.points).isEqualTo(10)
        assertThat(it.version).isNotNull()
      }
      .expectComplete()
      .verify()
  }

  @Test
  fun `Should fail on duplicate name`() {
    // Given
    val house = House(name = RandomStringUtils.randomAlphabetic(10), points = 10)

    // When
    create(subject.save(house))
      .expectSubscription()
      .assertNext {
        assertThat(it.name).isEqualTo(house.name)
      }
      .expectComplete()
      .verify()

    // Then
    create(subject.save(house))
      .expectSubscription()
      .expectError()
      .verify()
  }

  @Test
  fun `Should find house by name ignore case`() {
    // Given
    val house = House(name = "NAME", points = 10)

    // When
    create(subject.save(house))
      .expectSubscription()
      .assertNext {
        assertThat(it.id).isNotNull()
        assertThat(it.name).isEqualTo(house.name)
        assertThat(it.points).isEqualTo(10)
        assertThat(it.version).isNotNull()
      }
      .expectComplete()
      .verify()

    // Then
    create(subject.findByNameIgnoreCase("name"))
      .expectSubscription()
      .assertNext {
        assertThat(it.id).isNotNull()
        assertThat(it.name).isEqualTo(house.name)
      }
      .expectComplete()
      .verify()
  }
}